#pragma once
#include "Message.hpp"
#include "TcpMessage.hpp"
#include "sock/UdpSocket.hpp"
using std::cin;

void StartMenu(){
  cout << "+-----------------------------+" << endl;
  cout << "|    欢迎使用憨憨聊天系统     |" << endl;
  cout << "|    1. 已有账号? 登录.       |" << endl;
  cout << "|    2. 还没有账号? 注册.     |" << endl;
  cout << "|    3. 点错了, 退出          |" << endl;
  cout << "+-----------------------------+" << endl;
}

void CinClear(){
  cin.clear();
  cin.ignore(1024, '\n');
}

//输入合法性检查
bool HintInput(const std::string& hint, std::string& buf){
  cout << hint;
  cin >> buf;
  CinClear();
  if(buf.empty()){
    cout << "您的输入为空" << endl;
    return false;
  }
  return true;
}

class Client{
  public:
    Client()
    :myinfo(nullptr){
      tcp_sock.Init();
      udp_sock.Init();
      if(!tcp_sock.Create() || !udp_sock.Create()){
        exit(0);
      }
      if(!tcp_sock.Connect()){
        exit(1);
      }
      LOG("connect success!");
    }

    ~Client(){
      if(myinfo){
        delete myinfo;
      }
      tcp_sock.Close();
      udp_sock.Close();
    }

    //登录模块
    void Start(){
      int chose;
      int is_break = 1;
      while(is_break){
        ReplyInfo* svr_reply;
        StartMenu();
        cin >> chose;
        CinClear();
        switch(chose){
          case 1:
            if(!LoginOn()){
              LOG("send false!");
              exit(1);
            }
            break;
          case 2:
            if(!Register()){
              LOG("send false!");
              exit(2);
            }
            break;
          case 3:
            exit(0);
          default:
            cout << "输入有误, 请重新输入" << endl;
            continue;
        }
        std::string buf;
        tcp_sock.Recv(buf);
        svr_reply = (ReplyInfo*)((TcpMessage*)buf.data())->GetInfo();
        switch(svr_reply->reply){
          case USEREXIST:
            cout << "该用户已被注册!" << endl;
            break;
          case REGISTERSUCCESS:
            cout << "注册成功! 请登录" << endl;
            cout << "您的憨憨账号为:" << svr_reply->u_id << endl;
            break;
          case DIFICIENINFO:
            cout << "注册失败! 您的信息存在非法字符" << endl;
            break;
          case USERNONEXIST:
            cout << "用户不存在, 请先注册" << endl;
            break;
          case LOGINSUCCESS:
            is_break = 0;
            myinfo = new Message(svr_reply->u_id, WAITONLINE);
            cout << "登录成功!" << endl;
            break;
          case LOGINFAIL:
            cout << "账号或密码错误!" << endl;
            break;
          default:
            cout << "我也不知收到了个什么" << endl;
            break;
        }
      } 
      tcp_sock.Close();
      WaitOnline();
    }
   
    bool LoginOn(){
      LoginInfo info;
      ID_Type u_id;
      std::string input;
      while(1){
        cout << "账号:";
        cin >> u_id;
        CinClear();
        if(!HintInput("密码:", input)){
          continue;
        }
        if(input.size() > 127){
          cout << "密码错误!" << endl;
          continue;
        }
        break;
      }
      fflush(stdout);
      info.u_id = u_id;
      memcpy(info.pass_word, input.data(), input.size());
      std::string send_msg;
      TcpMessage(info).ToString(send_msg);
      if(!tcp_sock.Send(send_msg)){
        LOG("");
        return false;
      }
      return true;
    }

    bool Register(){
      RegisterInfo info;
      std::string tmp;
      while(1){
        if(!HintInput("昵称:", tmp)){
          continue;
        }
        if(tmp.size() > 127){
          cout << "昵称过长!" << endl;
          continue;
        }
        break;
      }
      memcpy(info.nick_name, tmp.data(), tmp.size());
      tmp.clear();
      while(1){
        if(!HintInput("学校:", tmp)){
          continue;
        }
        if(tmp.size() > 127){
          cout << "有这个学校?" << endl;
          continue;
        }
        break;
      }
      memcpy(info.school, tmp.data(), tmp.size());
      tmp.clear();
      while(1){
        std::string tmp2;
        if(!HintInput("密码:", tmp)){
          continue;
        }
        if(!HintInput("确认密码:", tmp2)){
          continue;
        }
        if(tmp != tmp2){
          cout << "两次输入的密码不一致!请重新输入" << endl;
          continue;
        }
        if(tmp.size() > 127){
          cout << "密码过长!" << endl;
          continue;
        }
        break;
      }
      fflush(stdout);
      memcpy(info.pass_word, tmp.data(), tmp.size());
      std::string send_msg;
      TcpMessage(info).ToString(send_msg);
      if(!tcp_sock.Send(send_msg)){
        LOG("");
        return false;
      }
      return true;
    }

    //登录成功后向server发送一个WAITONLINE请求
    void WaitOnline(){
      std::string buf;
      myinfo->Serialize(buf);
      udp_sock.Send(buf);
      udp_sock.Recv(buf);
      myinfo->Deserialize(buf);
    }

    //加载聊天菜单
    //选择模块:私聊, 群聊, 退出

    void OutLine(){
      myinfo->SetStatus(OUTLINE);
    }

    void SendMsg(std::string& msg){
      myinfo->AlterInfo(msg, MESSAGE);
      std::string send_msg;
      myinfo->Serialize(send_msg);
      udp_sock.Send(send_msg);
    }

    void RecvMsg(std::string& recv_msg){
      udp_sock.Recv(recv_msg);
    }

    const ID_Type& MyID(){
      return myinfo->GetID();
    }
  private:
    Message* myinfo;
    TcpSocket tcp_sock;
    UdpSocket udp_sock;
};
